package org.dfl.plugin.wizards;

import java.io.File;
import java.lang.reflect.InvocationTargetException;

import org.dfl.plugin.DflPlugin;
import org.dfl.plugin.Nature;
import org.dfl.plugin.ProjectConstraints;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IExecutableExtension;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;

/**
 * wizard used to create a new dfl project
 * @author Piotr Wlodarczyk
 *
 */
public class NewDflProjectWizard extends BasicNewProjectResourceWizard implements
		IExecutableExtension {

	public static final String ID = "openwfe.org.ide.ui.wizards.NewProjectWizard";//$NON-NLS-1$

	private WizardNewProjectCreationPage mainPage;

	// cache of newly-created project
	private IProject newProject;

	/**
	 * Creates a wizard for creating a new project resource in the workspace.
	 */
	public NewDflProjectWizard() {
		IDialogSettings workbenchSettings = DflPlugin.getDefault().getDialogSettings();
		IDialogSettings section = workbenchSettings
				.getSection("DflNewProjectResourceWizard");//$NON-NLS-1$
		if (section == null)
			section = workbenchSettings
					.addNewSection("DflNewProjectResourceWizard");//$NON-NLS-1$
		setDialogSettings(section);
	}

	/*
	 * (non-Javadoc) Method declared on IWizard.
	 */
	public void addPages() {
		mainPage = new WizardNewProjectCreationPage("openDflNewProjectPage");//$NON-NLS-1$
		mainPage.setTitle("New Dfl Project"); //$NON-NLS-1$
		mainPage.setDescription("Create a new Dfl Project"); //$NON-NLS-1$
		this.addPage(mainPage);
	}

	/**
	 * Creates a new project resource with the selected name.
	 * <p>
	 * In normal usage, this method is invoked after the user has pressed Finish
	 * on the wizard; the enablement of the Finish button implies that all
	 * controls on the pages currently contain valid values.
	 * </p>
	 * <p>
	 * Note that this wizard caches the new project once it has been
	 * successfully created; subsequent invocations of this method will answer
	 * the same project resource without attempting to create it again.
	 * </p>
	 *
	 * @return the created project resource, or <code>null</code> if the
	 *         project was not created
	 */
	private IProject createNewProject() {
		if (newProject != null)
			return newProject;

		// --[ GET A PROJECT HANDLE ]-------------------------------------------
		final IProject newProjectHandle = mainPage.getProjectHandle();

		// --[ GET A PROJECT DESCRIPTOR ]---------------------------------------
		IPath newPath = null;
		if (!mainPage.useDefaults())
			newPath = mainPage.getLocationPath();

		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		final IProjectDescription description = workspace.newProjectDescription(newProjectHandle.getName());
		description.setLocation(newPath);

		// --[ ADD A NATURE TO THE PROJECT DESCRIPTION ]------------------------

		String[] natures = description.getNatureIds();
		String[] newNatures = new String[natures.length + 1];
		System.arraycopy(natures, 0, newNatures, 0, natures.length);
		newNatures[natures.length] = Nature.ID;
		description.setNatureIds(newNatures);

		// --[ CREATE THE NEW PROJECT OPERATION ]-------------------------------
		WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
			protected void execute(IProgressMonitor monitor)
					throws CoreException {
				doCreateProject(description, newProjectHandle, monitor);
			}
		};

		// --[ RUN THE NEW PROJECT CREATION OPERATION ]-------------------------
		try {
			getContainer().run(true, true, op);
		} catch (InterruptedException e) {
			return null;
		} catch (InvocationTargetException e) {
			return null;
		}

		newProject = newProjectHandle;

		return newProject;
	}

	/**
	 * Creates a project resource given the project handle and description.
	 *
	 * @param description
	 *            the project description to create a project resource for
	 * @param projectHandle
	 *            the project handle to create a project resource for
	 * @param monitor
	 *            the progress monitor to show visual progress with
	 *
	 * @exception CoreException
	 *                if the operation fails
	 * @exception OperationCanceledException
	 *                if the operation is canceled
	 */
	void doCreateProject(IProjectDescription description, IProject projectHandle,
			IProgressMonitor monitor) throws CoreException,
			OperationCanceledException {
		try {
			monitor.beginTask("", 2000);//$NON-NLS-1$
			projectHandle.create(description, new SubProgressMonitor(monitor,1000));
			if (monitor.isCanceled())
				throw new OperationCanceledException();

			// do this carefully!
			String projectPath = projectHandle.getLocation().toFile().getAbsolutePath();
			
		    (new File(projectPath+ProjectConstraints.PROJECT_DIR_DIAGRAMS)).mkdirs();
		    (new File(projectPath+ProjectConstraints.PROJECT_DIR_STATES)).mkdirs();
		    (new File(projectPath+ProjectConstraints.PROJECT_DIR_TOKENS)).mkdirs();
		    (new File(projectPath+ProjectConstraints.PROJECT_DIR_HISTORIES)).mkdirs();
		    (new File(projectPath+ProjectConstraints.PROJECT_DIR_LIB)).mkdirs();
		    (new File(projectPath+ProjectConstraints.PROJECT_DIR_DATA)).mkdirs();
			
		    //refresh
		    projectHandle.refreshLocal(IProject.DEPTH_INFINITE, null);
			projectHandle.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(monitor, 1000));
		} finally {
			monitor.done();
		}
	}

	/**
	 * Returns the newly created project.
	 *
	 * @return the created project, or <code>null</code> if project not
	 *         created
	 */
	public IProject getNewProject() {
		return newProject;
	}

	/*
	 * (non-Javadoc) Method declared on BasicNewResourceWizard.
	 */
	@SuppressWarnings("static-access") //$NON-NLS-1$
	protected void initializeDefaultPageImageDescriptor() {
		ImageDescriptor desc = DflPlugin.getDefault().getImageDescriptor("icons/dfl.gif"); //$NON-NLS-1$
		setDefaultPageImageDescriptor(desc);
	}

	/*
	 * (non-Javadoc) Method declared on IWizard.
	 */
	public boolean performFinish() {
		createNewProject();

		if (newProject == null)
			return false;

		try {
			newProject.refreshLocal(IProject.DEPTH_INFINITE, null);
		} catch (CoreException e) {}
		updatePerspective();
		selectAndReveal(newProject);

		return true;
	}
}